from collections import Mapping, defaultdict, deque
from contextlib import closing, contextmanager
from functools import partial
from operator import attrgetter
from weakref import WeakValueDictionary
import logging
import os
import threading

import odoo
from .. import SUPERUSER_ID
from odoo.sql_db import TestCursor
from odoo.tools import (assertion_report, config, existing_tables,
                        lazy_classproperty, lazy_property, table_exists,
                        topological_sort, OrderedSet)
from odoo.tools.lru import LRU

_logger = logging.getLogger(__name__)

class Registry(Mapping):
    _lock = threading.RLock()
    _saved_lock = None

    model_cache = WeakValueDictionary()

    @lazy_classproperty
    def registries(cls):
        pass

    def __new__(cls, db_name):
        pass

    @classmethod
    def new(cls, db_name, force_demo=False, status=None, update_module=False):
        with cls._lock:
            with odoo.api.Environment.manage():
                registry = object.__new__(cls)
                registry.init(db_name)

    def init(self, db_name):
        self.models = {}  # model name/model instance mapping
        self._sql_error = {}
        self._init = True
        self._assertion_report = assertion_report.assertion_report()
        self._fields_by_model = None
        self._post_init_queue = deque()
        self._notnull_errors = {}

        # modules fully loaded (maintained during init phase by `loading` module)
        self._init_modules = set()
        self.updated_modules = []  # installed/updated modules
        self.loaded_xmlids = set()

        self.db_name = db_name
        self._db = odoo.sql_db.db_connect(db_name)

        self.test_cr = None
        self.test_lock = None

        # Indicates that the registry is
        self.loaded = False  # whether all modules are loaded
        self.ready = False  # w

        self.registry_sequence = None
        self.cache_sequence = None

        # Flags indicating invalidation of the registry or the cache.
        self._invalidation_flags = threading.local()
        with closing(self.cursor()) as cr:
            has_unaccent = odoo.modules.db.has_unaccent(cr)
            if odoo.tools.config['unaccent'] and not has_unaccent:
                pass

    @classmethod
    def delete(cls, db_name):
        pass

    @classmethod
    def delete_all(cls):
        pass

    def __len__(self):
        pass

    def __iter__(self):
        pass

    def __getitem__(self, model_name):
        pass

    def __call__(self, model_name):
        pass

    def __setitem__(self, model_name, model):
        pass

    @lazy_property
    def field_sequence(self):
        pass

    @classmethod
    def delete(cls, db_name):
        pass

    @classmethod
    def delete_all(cls):
        pass

    def descendants(self, model_names, *kinds):
        pass

    def load(self, cr, module):
        pass

    def setup_models(self, cr):
        pass

    def post_init(self, func, *args, **kwargs):
        pass

    def init_models(self, cr, model_names, context):
        pass

    def check_tables_exist(self, cr):
        pass

    @lazy_property
    def cache(self):
        pass

    def _clear_cache(self):
        pass

    def clear_caches(self):
        pass

    @property
    def registry_invalidated(self):
        pass

    @registry_invalidated.setter
    def registry_invalidated(self, value):
        pass

    @property
    def cache_invalidated(self):
        pass

    @cache_invalidated.setter
    def cache_invalidated(self, value):
        pass

    def setup_signaling(self):
        pass

    def check_signaling(self):
        pass

    def signal_changes(self):
        pass

    def reset_changes(self):
        pass

    @contextmanager
    def manage_changes(self):
        pass

    def in_test_mode(self):
        pass

    def enter_test_mode(self, cr):
        pass

    def leave_test_mode(self):
        pass

    def cursor(self):
        if self.test_cr is not None:
            pass
        return self._db.cursor()

class DummyRLock(object):
    def acquire(self):
        pass
    def release(self):
        pass
    def __enter__(self):
        pass
    def __exit__(self, type, value, traceback):
        pass